import random
import numpy as np
from view.loadSaveDB import loadSaveDB


class RandomSampling:

    def __init__(self, data, label):
        self.data = data
        self.rows = data.shape[0]
        self.label = label
        self.cluster = len(np.unique(label))
        self.randomSampleBlocks = None
        self.randomSampleBlocks_labels = None

    def randomPartition(self, blocks):
        idxs = list(range(self.rows))
        random.shuffle(idxs)
        idxs = np.reshape(idxs, (blocks, -1))

        self.randomSampleBlocks = []
        self.randomSampleBlocks_labels = []
        for blockidxs in idxs:
            self.randomSampleBlocks.append(self.data[blockidxs, :])
            self.randomSampleBlocks_labels.append(self.label[blockidxs])
        self._fixLabels()

    def _fixLabels(self):
        fixedLabels = []
        for label in self.randomSampleBlocks_labels:
            fixedLabels.append(label)
            label_block = np.unique(label)
            nclusters_block = len(label_block)
            if list(label_block) == list(range(nclusters_block)):
                continue
            for i, t in enumerate(label_block):
                idxs = np.where(label == t)[0]
                label[idxs] = i
            fixedLabels[-1] = label
        self.randomSampleBlocks_labels = fixedLabels

    def simplePartition(self, blocks, isEven):
        idxs = np.array(range(self.rows))

        if isEven:
            gap1 = int(self.rows * 0.6)
            gap2 = int(self.rows * 0.4)
            assert gap2 < gap1

            evenIds = list(range(gap1))
            random.shuffle(evenIds)
            idxs[:gap1] = idxs[evenIds]

            evenIds = list(range(gap2, self.rows))
            random.shuffle(evenIds)
            idxs[gap2:] = idxs[evenIds]

        idxs = idxs.tolist()
        idxs = np.reshape(idxs, (blocks, -1))

        self.randomSampleBlocks = []
        self.randomSampleBlocks_labels = []
        for blockidxs in idxs:
            self.randomSampleBlocks.append(self.data[blockidxs, :])
            self.randomSampleBlocks_labels.append(self.label[blockidxs])
        self._fixLabels()

    def saveToDB(self, des, fileName, name):
        lsd = loadSaveDB()
        ids = []
        for data, label in zip(self.randomSampleBlocks, self.randomSampleBlocks_labels):
            data = np.concatenate((label[:, np.newaxis], data), axis=1)
            id = lsd.saveDBForDataset(data=data, des=des, fileName=fileName, nClusters=max(label)+1, name=name,
                                      haveLabels=True, confirm=True)
            ids.append(id)
        return ids
